/*
 * @file     g_bpu.c
 * @brief    This file provides all the BPU firmware functions.
 *
 * Change Logs:
 * Date           Author             Version        Notes
 * 2021-05-26     xubo               V1.0.0         the first version
 */

/* Includes -----------------------------------------------------------------*/
#include "g_bpu.h"
#define BPK_KEY_NUM 32
/* Exported functions -------------------------------------------------------*/
/**
 * @method G_BPU_IsReady
 * @brief  Check whether bpu is ready or not
 * @param  None
 * @retval The status of BPU ready flag
 */
static G_FlagStatus G_BPU_IsReady(void)
{
    if (ENABLE == MSYSCTRL->LPM_BUSY_CFG.bit.LPM_EN)
    {
        return SET;
    }

    return RESET;
}
/**
 * @method G_BPU_Init
 * @brief  BPU module initializes the vector
 * @param  none
 * @retval result of operation
 */
G_ErrorStatus G_BPU_Init(void)
{
    if (RESET == G_BPU_IsReady())
    {
        return ERROR;
    }

    G_LPM_AccessCode(ENABLE);
    G_LPM_RegisterClk(ENABLE);

    return SUCCESS;
}

/**
 * @method G_BPU_Reset
 * @brief  BPU module reset the vector
 * @param  none
 * @retval result of operation
 */
G_ErrorStatus G_BPU_Reset(void)
{
    if (RESET == G_BPU_IsReady())
    {
        return ERROR;
    }

    MBPK->RST.reg = ENABLE;

    return SUCCESS;
}

/**
 * @method G_BPU_ITCmd
 * @brief  Safety interrupt master switch
 * @param  status: new state of the BPK region write lock
 *                 This parameter can be ENABLE or DISABLE
 * @retval None
 */
void G_BPU_ITCmd(G_FunctionalState NewState)
{
    MSECURE->IE.bit.IE = NewState;
    MSECURE->IE.bit.CORE_IE = NewState;
}

/**
 * @method G_BPK_WriteKey
 * @brief  write user key from the specified Data backup register
 * @param  buf        : pointer to the data to write
 * @param  key_len    : length of user key
 * @param  key_offset : offset of the Data backup register
 * @retval result of operation
 */
G_ErrorStatus G_BPK_WriteKey(uint32_t *buf, uint32_t key_len, uint32_t key_offset)
{
    uint32_t index = 0;

    if (key_offset + key_len > BPK_KEY_NUM)
    {
        return ERROR;
    }

	G_LPM_AccessCode(ENABLE);
    G_LPM_RegisterClk(ENABLE);

    for (index = 0; index < key_len; index++)
    {
        MBPK->KEY[key_offset + index] = buf[index];
    }

    return SUCCESS;
}

/**
 * @method G_BPK_ReadKey
 * @brief  read user key from the specified Data backup register
 * @param  buf        : pointer to the data to read
 * @param  key_len    : length of user key
 * @param  key_offset : offset of the Data backup register
 * @retval result of operation
 */
G_ErrorStatus G_BPK_ReadKey(uint32_t *buf, uint32_t key_len, uint32_t key_offset)
{
    uint32_t index = 0;

    if (key_offset + key_len > BPK_KEY_NUM)
    {
        return ERROR;
    }

	G_LPM_AccessCode(ENABLE);
    G_LPM_RegisterClk(ENABLE);

    for (index = 0; index < key_len; index++)
    {
        buf[index] = MBPK->KEY[key_offset + index];
    }

    return SUCCESS;
}

/**
 * @method G_BPK_KeyClear
 * @brief  Clear the specified Data backup region
 * @param  bpk_key_region: Data backup region
 *         This parameter can be one of the following values:
 *         @arg BPK_KEY_REGION_0
 *         @arg BPK_KEY_REGION_1
 *         @arg BPK_KEY_REGION_2
 *         @arg BPK_KEY_REGION_3
 * @retval None
 */
void G_BPK_KeyClear(uint16_t bpk_key_region)
{
    _ASSERT(IS_BPK_KEY_REGION(bpk_key_region));

    MBPK->CLR.reg = bpk_key_region;
}

/**
 * @method G_BPK_AlterClearKey
 * @brief  Select whether to clear the key when alarm occurs.
 * @param  NewState: new state of the BPK alarm action
 *                   This parameter can be ENABLE or DISABLE
 * @retval None
 */
void G_BPK_AlterClearKey(G_FunctionalState NewState)
{
    _ASSERT(IS_FUNCTIONAL_STATE(NewState));

    if(NewState != ENABLE)
    {
        MSEC->ALERT_ACTION.bit.CLEAR_KEY = 0x5;
    }
    else
    {
        MSEC->ALERT_ACTION.bit.CLEAR_KEY = 0xa;
    }
}

/**
 * @method G_BPK_KeyWriteLock
 * @brief  Enable or disable Data backup register write lock
 * @param  bpk_key_region: Data backup region
 *         This parameter can be one of the following values:
 *         @arg BPK_KEY_REGION_0
 *         @arg BPK_KEY_REGION_1
 *         @arg BPK_KEY_REGION_2
 *         @arg BPK_KEY_REGION_3
 * @param  status: new state of the BPK region write lock
 *                 This parameter can be ENABLE or DISABLE
 * @retval None
 */
void G_BPK_KeyWriteLock(uint16_t bpk_key_region, G_FunctionalState status)
{
    _ASSERT(IS_BPK_KEY_REGION(bpk_key_region));

    if (DISABLE != status)
    {
        MBPK->LW.bit.LOCK_WRITE |= bpk_key_region;
    }
    else
    {
        MBPK->LW.bit.LOCK_WRITE &= ~bpk_key_region;
    }
}

/**
 * @method G_BPK_KeyReadLock
 * @brief  Enable or disable Data backup register read lock
 * @param  bpk_key_region: Data backup region
 *         This parameter can be one of the following values:
 *         @arg BPK_KEY_REGION_0
 *         @arg BPK_KEY_REGION_1
 *         @arg BPK_KEY_REGION_2
 *         @arg BPK_KEY_REGION_3
 * @param  status: new state of the BPK region read lock
 *                 This parameter can be ENABLE or DISABLE
 * @retval None
 */
void G_BPK_KeyReadLock(uint16_t bpk_key_region, G_FunctionalState status)
{
    _ASSERT(IS_BPK_KEY_REGION(bpk_key_region));

    if (DISABLE != status)
    {
        MBPK->LR.bit.LOCK_READ |= bpk_key_region;
    }
    else
    {
        MBPK->LR.bit.LOCK_READ &= ~bpk_key_region;
    }
}

/**
 * @method G_BPK_Lock
 * @brief  Choose whether to enable or disbale BPK lock.
 * @param  bpk_locks: specify the bpk lock
 *         This parameter can be one of the following values:
 *         @arg BPK_LR_LOCK_KEYWRITE
 *         @arg BPK_LR_LOCK_KEYREAD
 *         @arg BPK_LR_LOCK_KEYCLEAR
 *         @arg BPK_LR_LOCK_RESET
 *         @arg BPK_LR_LOCK_ALL
 * @param  status: new state of the specified BPK lock
 *                 This parameter can be ENABLE or DISABLE
 * @retval None
 */
void G_BPK_Lock(uint32_t bpk_locks, G_FunctionalState status)
{
    _ASSERT((bpk_locks != BPK_LR_LOCK_SELF) && IS_BPK_LOCK(bpk_locks));

    if (DISABLE != status)
    {
        MBPK->LOCK.reg |= bpk_locks;
    }
    else
    {
        MBPK->LOCK.reg &= ~bpk_locks;
    }
}

/**
 * @method G_BPK_LockSelf
 * @brief  Lock the BPK_LR register
 *         Note: If the BPK_LR register is locked, only through backup battery domain power on again can be unlocked
 * @param  None
 * @retval None
 */
void G_BPK_LockSelf(void)
{
    MBPK->LOCK.reg |= BPK_LR_LOCK_SELF;
}

/**
 * @method G_BPK_GetLockStatus
 * @brief  Get the specified BPK lock status
 * @param  bpk_locks: specify the bpk lock
 *         This parameter can be one of the following values:
 *         @arg BPK_LR_LOCK_SELF
 *         @arg BPK_LR_LOCK_KEYWRITE
 *         @arg BPK_LR_LOCK_KEYREAD
 *         @arg BPK_LR_LOCK_KEYCLEAR
 *         @arg BPK_LR_LOCK_RESET
 *         @arg BPK_LR_LOCK_ALL
 * @retval result of operation
 */
G_FlagStatus G_BPK_GetLockStatus(uint32_t bpk_locks)
{
    _ASSERT(IS_BPK_LOCK(bpk_locks));

    if ((MBPK->LOCK.reg & bpk_locks) != (uint16_t)RESET)
    {
        return SET;
    }
    else
    {
        return RESET;
    }
}

#if 0
/**
 * @method G_SENSOR_EXTInit
 * @brief  Sensor Init
 * @param  SENSOR_EXTInitStruct: SENSOR_EXTInitStruct
 * @retval result of operation
 */
uint32_t G_SENSOR_EXTInit(G_SENSOR_EXTInitTypeDef *SENSOR_EXTInitStruct)
{
    _ASSERT(IS_SENSOR_PORT(SENSOR_EXTInitStruct->SENSOR_Port_Static | SENSOR_EXTInitStruct->SENSOR_Port_Dynamic));
    _ASSERT(IS_SENSOR_PORT_IE(SENSOR_EXTInitStruct->SENSOR_Port_IE));
    _ASSERT(IS_SENSOR_PORT_PUPD(SENSOR_EXTInitStruct->SENSOR_Port_PU | SENSOR_EXTInitStruct->SENSOR_Port_PD));
    _ASSERT(IS_PERIOD_STATIC(SENSOR_EXTInitStruct->SENSOR_Static_Period));
    _ASSERT(IS_PERIOD_DYNAMIC(SENSOR_EXTInitStruct->SENSOR_Dynamic_Period));
    _ASSERT(IS_SENSOR_EXT_STATIC_CHECK(SENSOR_EXTInitStruct->SENSOR_Static_Chk_Num));
    _ASSERT(IS_SENSOR_EXT_DYNAMIC_CHECK(SENSOR_EXTInitStruct->SENSOR_Dynamic_Chk_Num));
    _ASSERT(IS_FUNCTIONAL_STATE(SENSOR_EXTInitStruct->SENSOR_Static_Alert_Port_En));
    _ASSERT(IS_FUNCTIONAL_STATE(SENSOR_EXTInitStruct->SENSOR_Dynamic_Alert_Port_En));
    _ASSERT(IS_ALERT_Port_Mode(SENSOR_EXTInitStruct->SENSOR_Static_Alert_Port_Mode));
    _ASSERT(IS_ALERT_Port_Mode(SENSOR_EXTInitStruct->SENSOR_Dynamic_Alert_Port_Mode));
    _ASSERT(IS_FUNCTIONAL_STATE(SENSOR_EXTInitStruct->SENSOR_Static_Pull_Auto));
    _ASSERT(IS_SENSOR_ALERT_LEVEL(SENSOR_EXTInitStruct->SENSOR_Static_Alert_H | SENSOR_EXTInitStruct->SENSOR_Static_Alert_H));

    uint32_t i = 0;
    volatile uint32_t tmpSensorExtType     = 0;
    volatile uint32_t tmpSensorExtPullPd   = 0;
    volatile uint32_t tmpSensorExtPullPu   = 0;
    volatile uint32_t tmpSensorExtState    = 0;
    volatile uint32_t tmpSensorExtEnable   = 0;

    /*simple rule check,each pin can be used only one mode*/
    if (SENSOR_EXTInitStruct->SENSOR_Port_Static & SENSOR_EXTInitStruct->SENSOR_Port_Dynamic)
    {
        return 1;
    }

    /*simple rule check, each pin can be used only one mode*/
    if (SENSOR_EXTInitStruct->SENSOR_Port_PU & SENSOR_EXTInitStruct->SENSOR_Port_PD)
    {
        return 2;
    }

    /*simple rule check, each pin can be used only one mode*/
    if (SENSOR_EXTInitStruct->SENSOR_Static_Alert_H & SENSOR_EXTInitStruct->SENSOR_Static_Alert_L)
    {
        return 3;
    }

    /*configure the external detachable IO dynamic or static mode configuration*/
    for (i = 0; i < EXT_SENSOR_NUM / 2; i++)
    {
        if (0 != (SENSOR_EXTInitStruct->SENSOR_Port_Dynamic & (0x3 << i * 2)))
        {
            tmpSensorExtType |= 0x01 << i;
        }
    }
    MSEC->TAMP_CTRL.bit.MODE = RESET;
    MSEC->TAMP_CTRL.bit.MODE = tmpSensorExtType;

    /*configure the external detachable IO IE configuration*/
    MSEC->TAMP_CTRL.bit.IE = RESET;
    MSEC->TAMP_CTRL.bit.IE = SENSOR_EXTInitStruct->SENSOR_Port_IE;

    /*external anti-demolition IO pull up and down status configuration*/
    for (i = 0; i < EXT_SENSOR_NUM; i++)
    {
        if (0 != (SENSOR_EXTInitStruct->SENSOR_Port_PD & (0x1 << i)))
        {
            tmpSensorExtPullPd |= 0x01 << i;
        }
        if (0 != (SENSOR_EXTInitStruct->SENSOR_Port_PU & (0x1 << i)))
        {
            tmpSensorExtPullPu |= 0x01 << i;
        }
    }
    MSEC->TAMP_CTRL.bit.PD_EN = RESET;
    MSEC->TAMP_CTRL.bit.PD_EN = tmpSensorExtPullPd;
    MSEC->TAMP_CTRL.bit.PU_EN = 0xff;
    MSEC->TAMP_CTRL.bit.PU_EN = tmpSensorExtPullPu;

    /*external anti-demolition IO detection cycle configuration*/
    MSEC->TAMP_STA_CTRL.bit.PERIOD = RESET;
    MSEC->TAMP_STA_CTRL.bit.PERIOD = SENSOR_EXTInitStruct->SENSOR_Static_Period;
    MSEC->TAMP_DYN_CTRL.bit.PERIOD = RESET;
    MSEC->TAMP_DYN_CTRL.bit.PERIOD = SENSOR_EXTInitStruct->SENSOR_Dynamic_Period;

    /*the number of single cycle detection of external anti-demolition IO*/
    MSEC->TAMP_STA_CTRL.bit.CHK_WIN = RESET;
    MSEC->TAMP_STA_CTRL.bit.CHK_WIN = SENSOR_EXTInitStruct->SENSOR_Static_Chk_Num;
    MSEC->TAMP_DYN_CTRL.bit.CHK_WIN = RESET;
    MSEC->TAMP_DYN_CTRL.bit.CHK_WIN = SENSOR_EXTInitStruct->SENSOR_Dynamic_Chk_Num;

    /*external static anti-demolition IO filter window number*/
    MSEC->TAMP_STA_CTRL.bit.FILT_WIN = RESET;
    MSEC->TAMP_STA_CTRL.bit.FILT_WIN = SENSOR_EXTInitStruct->SENSOR_Static_Fit_Win;

    /*Whether to start automatic protection after external static and dynamic IO alarm is triggered*/
    MSEC->TAMP_STA_CTRL.bit.PROT_EN = RESET;
    MSEC->TAMP_STA_CTRL.bit.PROT_EN = SENSOR_EXTInitStruct->SENSOR_Static_Alert_Port_En;
    MSEC->TAMP_DYN_CTRL.bit.PROT_EN = RESET;
    MSEC->TAMP_DYN_CTRL.bit.PROT_EN = SENSOR_EXTInitStruct->SENSOR_Dynamic_Alert_Port_En;

    /*Mode control after external dynamic and static sensor alarm*/
    MSEC->TAMP_STA_CTRL.bit.PROT_MODE = RESET;
    MSEC->TAMP_STA_CTRL.bit.PROT_MODE = SENSOR_EXTInitStruct->SENSOR_Static_Alert_Port_Mode;
    MSEC->TAMP_DYN_CTRL.bit.PROT_MODE = RESET;
    MSEC->TAMP_DYN_CTRL.bit.PROT_MODE = SENSOR_EXTInitStruct->SENSOR_Dynamic_Alert_Port_Mode;

    /*External static sensor pull up and down whether automatic control*/
    MSEC->TAMP_STA_CTRL.bit.PULL_AUTO = RESET;
    MSEC->TAMP_STA_CTRL.bit.PULL_AUTO = SENSOR_EXTInitStruct->SENSOR_Static_Pull_Auto;

    /*external static detachable IO trigger level configuration*/
    for (i = 0; i < EXT_SENSOR_NUM; i++)
    {
        if (0 != (SENSOR_EXTInitStruct->SENSOR_Static_Alert_H & (0x1 << i)))
        {
            tmpSensorExtState |= 0x01 << i;
        }
        else
        {
            tmpSensorExtState &= ~(0x01 << i);
        }
    }
    MSEC->TAMP_STA_CTRL.bit.ALERT_LEVEL = RESET;
    MSEC->TAMP_STA_CTRL.bit.ALERT_LEVEL = tmpSensorExtState;

    /*External static sensors detect intervals*/
    MSEC->TAMP_STA_CTRL.bit.CHK_GAP = RESET;
    MSEC->TAMP_STA_CTRL.bit.CHK_GAP = SENSOR_EXTInitStruct->SENSOR_Static_Chk_Gap;

    /*External static sensors pull up and down ahead of time*/
    MSEC->TAMP_STA_CTRL.bit.CHK_DLY = RESET;
    MSEC->TAMP_STA_CTRL.bit.CHK_DLY = SENSOR_EXTInitStruct->SENSOR_Static_Chk_Dly;

    /*configure the external detachable IO dynamic or static mode configuration*/
    for (i = 0; i < EXT_SENSOR_NUM; i++)
    {
        if (0 != ((SENSOR_EXTInitStruct->SENSOR_Port_Static | SENSOR_EXTInitStruct->SENSOR_Port_Dynamic) & (0x1 << i)))
        {
            SENSOR_T_S_PORT_ENABLE(tmpSensorExtEnable, i);
        }
        else
        {
            SENSOR_T_S_PORT_DISABLE(tmpSensorExtEnable, i);
        }
    }
    MSEC->TAMP_EN.reg = 0x55555555;
    MSEC->TAMP_EN.reg = tmpSensorExtEnable;

    return 0;
}
/**
 * @method G_SENSOR_EXTPortCmd
 * @brief  Enable or disable the tamper port.
 * @param  SensorPort: the port of tamper
 *         This parameter can be one of the following values:
 *         @arg SENSOR_Port_S0
 *         @arg SENSOR_Port_S1
 *         @arg SENSOR_Port_S2
 *         @arg SENSOR_Port_S3
 *         @arg SENSOR_Port_S4
 *         @arg SENSOR_Port_S5
 *         @arg SENSOR_Port_S6
 *         @arg SENSOR_Port_S7
 * @param  NewState: new state of the sensor check
 *                 This parameter can be ENABLE or DISABLE
 * @retval  None
 */
void G_SENSOR_EXTPortCmd(uint32_t SensorPort, G_FunctionalState NewState)
{
    uint32_t i = 0;
    volatile uint32_t tmpSensorExtPortEn = 0;

    _ASSERT(IS_SENSOR_PORT(SensorPort));

    tmpSensorExtPortEn = MSEC->TAMP_EN.reg;

    for (i = 0; i < EXT_SENSOR_NUM; i++)
    {
        if (0 != (SensorPort & (0x1 << i)))
        {
            if (DISABLE != NewState)
            {
                SENSOR_T_S_PORT_CLEAR(tmpSensorExtPortEn, i);
                SENSOR_T_S_PORT_ENABLE(tmpSensorExtPortEn, i);
            }
            else
            {
                SENSOR_T_S_PORT_CLEAR(tmpSensorExtPortEn, i);
                SENSOR_T_S_PORT_DISABLE(tmpSensorExtPortEn, i);
            }
        }
    }

    MSEC->TAMP_EN.reg = tmpSensorExtPortEn;
}
/**
 * @method G_SENSOR_ANAConfig
 * @brief  Config the length of Sensor detection time and Sensor alarm duration threshold.
 * @param  dur: length of Sensor detection time
 *         This parameter can be one of the following values:
 *         @arg SENSOR_ANA_DUR_ALWAYS_ON
 *         @arg SENSOR_ANA_DUR_2MS
 *         @arg SENSOR_ANA_DUR_8MS
 *         @arg SENSOR_ANA_DUR_16MS
 * @param  delay: Sensor alarm duration threshold
 *         This parameter can be one of the following values:
 *         @arg SENSOR_ANA_DEALY_31_25US
 *         @arg SENSOR_ANA_DEALY_250US
 *         @arg SENSOR_ANA_DEALY_1MS
 *         @arg SENSOR_ANA_DEALY_4MS
 * @retval  None
 */
void G_SENSOR_ANAConfig(uint32_t dur, uint32_t delay)
{
    _ASSERT(IS_SENSOR_ANA_DUR(dur));
    _ASSERT(IS_SENSOR_ANA_DELAY(delay));

    MSEC->SENSOR_CTRL.bit.DUR = dur;
    MSEC->SENSOR_CTRL.bit.DELAY = delay;
}

/**
 * @method G_SENSOR_ANACmd
 * @brief  Configure which sensor to use
 * @param  SensorAna: sensors
 *         This parameter can be one of the following values:
 *         @arg SENSOR_ANA_VBUT_1_2L
 *         @arg SENSOR_ANA_VBUT_3_3H
 *         @arg SENSOR_ANA_VBUT_3_3L
 *         @arg SENSOR_ANA_TEMPERA_H
 *         @arg SENSOR_ANA_TEMPERA_L
 * @param  NewState: new state of the sensor
 *                 This parameter can be ENABLE or DISABLE
 * @retval  None
 */
void G_SENSOR_ANACmd(uint32_t SensorAna, G_FunctionalState NewState)
{
    _ASSERT(IS_SENSOR_ANA(SensorAna));

    uint32_t i = 0;

    for (i = 0; i < INNER_SENSOR_NUM; i++)
    {
        if (DISABLE != NewState)
        {
            if (SensorAna & (BIT0 << i))
                MSEC->SENSOR_CTRL.bit.CHK_EN |= (BIT0 << i);
        }
        else
        {
            if (SensorAna & (BIT0 << i))
                MSEC->SENSOR_CTRL.bit.CHK_EN &= ~(BIT0 << i);
        }
    }
    if (DISABLE != NewState)
    {
        if (SensorAna & SENSOR_ANA_VBUT_1_2L)
        {
            MSEC->SENSOR_EN.bit.VBUT_1_2_EN = 0xa;
        }
        if (SensorAna & (SENSOR_ANA_VBUT_3_3H | SENSOR_ANA_VBUT_3_3L))
        {
            MSEC->SENSOR_EN.bit.VBUT_3_3_EN = 0xa;
        }
        if (SensorAna & (SENSOR_ANA_TEMPERA_H | SENSOR_ANA_TEMPERA_L))
        {
            MSEC->SENSOR_EN.bit.TEMP_EN = 0xa;
        }
    }
    else
    {
        if (SensorAna & SENSOR_ANA_VBUT_1_2L)
        {
            MSEC->SENSOR_EN.bit.VBUT_1_2_EN = 0x5;
        }
        if (SensorAna & (SENSOR_ANA_VBUT_3_3H | SENSOR_ANA_VBUT_3_3L))
        {
            MSEC->SENSOR_EN.bit.VBUT_3_3_EN = 0x5;
        }
        if (SensorAna & (SENSOR_ANA_TEMPERA_H | SENSOR_ANA_TEMPERA_L))
        {
            MSEC->SENSOR_EN.bit.TEMP_EN = 0x5;
        }
    }
}

/**
 * @method G_SENSOR_ChkConfig
 * @brief  Enable or disable sensor check.
 * @param  SensorAna: sensors
 *         This parameter can be one of the following values:
 *         @arg SENSOR_ANA_VBUT_1_2L
 *         @arg SENSOR_ANA_VBUT_3_3H
 *         @arg SENSOR_ANA_VBUT_3_3L
 *         @arg SENSOR_ANA_TEMPERA_H
 *         @arg SENSOR_ANA_TEMPERA_L
 * @param  NewState: new state of the sensor check
 *                 This parameter can be ENABLE or DISABLE
 * @retval  None
 */
void G_SENSOR_ChkConfig(uint32_t SensorAna, G_FunctionalState NewState)
{
    _ASSERT(IS_SENSOR_ANA(SensorAna));
    uint32_t i = 0;
    for (i = 0; i < INNER_SENSOR_NUM; i++)
    {
        if (DISABLE != NewState)
        {
            if (SensorAna & (BIT0 << i))
                MSEC->SENSOR_CTRL.bit.CHK_EN |= (BIT0 << i);
        }
        else
        {
            if (SensorAna & (BIT0 << i))
                MSEC->SENSOR_CTRL.bit.CHK_EN &= ~(BIT0 << i);
        }
    }
}

/**
 * @method G_SENSOR_Config
 * @brief  Enable or disable sensor total switch.
 * @param  SensorAna: sensors
 *         This parameter can be one of the following values:
 *         @arg SENSOR_ANA_VBUT_1_2L
 *         @arg SENSOR_ANA_VBUT_3_3H
 *         @arg SENSOR_ANA_VBUT_3_3L
 *         @arg SENSOR_ANA_TEMPERA_H
 *         @arg SENSOR_ANA_TEMPERA_L
 * @param  NewState: new state of the sensor check
 *                 This parameter can be ENABLE or DISABLE
 * @retval  None
 */
void G_SENSOR_Config(uint32_t SensorAna, G_FunctionalState NewState)
{
    _ASSERT(IS_SENSOR_ANA(SensorAna));
    if (DISABLE != NewState)
    {
        if (SensorAna & SENSOR_ANA_VBUT_1_2L)
        {
            MSEC->SENSOR_EN.bit.VBUT_1_2_EN = 0xa;
        }
        if (SensorAna & (SENSOR_ANA_VBUT_3_3H | SENSOR_ANA_VBUT_3_3L))
        {
            MSEC->SENSOR_EN.bit.VBUT_3_3_EN = 0xa;
        }
        if (SensorAna & (SENSOR_ANA_TEMPERA_H | SENSOR_ANA_TEMPERA_L))
        {
            MSEC->SENSOR_EN.bit.TEMP_EN = 0xa;
        }
    }
    else
    {
        if (SensorAna & SENSOR_ANA_VBUT_1_2L)
        {
            MSEC->SENSOR_EN.bit.VBUT_1_2_EN = 0x5;
        }
        if (SensorAna & (SENSOR_ANA_VBUT_3_3H | SENSOR_ANA_VBUT_3_3L))
        {
            MSEC->SENSOR_EN.bit.VBUT_3_3_EN = 0x5;
        }
        if (SensorAna & (SENSOR_ANA_TEMPERA_H | SENSOR_ANA_TEMPERA_L))
        {
            MSEC->SENSOR_EN.bit.TEMP_EN = 0x5;
        }
    }
}

/**
 * @method G_SENSOR_ANADvddLpmConfig
 * @brief  Dvdd threshold voltage selection.
 * @param  vthsel: threshold voltage select.
 * @retval  None
 */

void G_SENSOR_ANADvddLpmConfig(uint8_t vthsel)
{
    G_LPM_AccessCode(ENABLE);
    G_LPM_RegisterClk(ENABLE);
    uint8_t Cinfo = 0;
    uint8_t Addr13F = 0;
    G_OTP_Read(0x0a,&Cinfo,1);
    G_OTP_Read(0x13f,&Addr13F,1);
    if((Cinfo == 0x0) && (Addr13F == 0x0))
    {
       MSEC->SENSOR_THRES.bit.DVDDLPM_L = vthsel;
    }
    else
    {
        if((vthsel != 0x01) && (vthsel != 0x02) && (vthsel != 0x04) && (vthsel!=0))
        {
            return;
        }
        uint32_t ldo_por = MLPM->LDO_POR.reg;
        ldo_por &= ~(7 << 1);
        MLPM->LDO_POR.reg = ldo_por | (vthsel << 1);
    }
}

/**
 * @method G_SENSOR_ANAVbutConfig
 * @brief  Vbut threshold voltage selection.
 * @param  vthhsel: threshold voltage high select.
 *         This parameter can be one of the following values:
 *         @arg 0000: 3.471 V
 *         @arg 0001: 3.577 V
 *         @arg 0010: 3.690 V
 *         @arg 0011: 3.810 V
 *         @arg 0100: 3.938 V
 *         @arg 0101: 4.076 V
 *         @arg 0110: 4.223 V
 *         @arg 0111: 4.381 V
 *         @arg 1000: 4.552 V
 *         @arg 1001: 4.736 V
 *         @arg 1010: 4.936 V
 *         @arg 1011: 5.154 V
 *         @arg 1100: 5.392 V
 *         @arg 1101: 5.653 V
 *         @arg 1110: 5.926 V
 *         @arg 1111: 6.115 V
 * @param  vthlsel: threshold voltage low select.
 *         This parameter can be one of the following values:
 *         @arg 0000: 1.938 V
 *         @arg 0001: 1.971 V
 *         @arg 0010: 2.005 V
 *         @arg 0011: 2.040 V
 *         @arg 0100: 2.076 V
 *         @arg 0101: 2.113 V
 *         @arg 0110: 2.152 V
 *         @arg 0111: 2.193 V
 *         @arg 1000: 2.235 V
 *         @arg 1001: 2.278 V
 *         @arg 1010: 2.324 V
 *         @arg 1011: 2.371 V
 *         @arg 1100: 2.420 V
 *         @arg 1101: 2.471 V
 *         @arg 1110: 2.525 V
 *         @arg 1111: 2.580 V
 * @retval  None
 */
void G_SENSOR_ANAVbutConfig(uint8_t vthhsel, uint8_t vthlsel)
{
    MSEC->SENSOR_THRES.bit.VBUT_H = vthhsel;
    MSEC->SENSOR_THRES.bit.VBUT_L = vthlsel;
}

/**
 * @method G_SENSOR_ANATsConfig
 * @brief  Temperature detector control.
 * @param  :utc: Temperature detector under-temperature control.
 *         This parameter can be one of the following values:
 *         @arg 0: -38℃
 *         @arg 1: -33℃
 *         @arg 2: -28℃
 *         @arg 3: -22℃
 *         @arg 4: -17℃
 *         @arg 5: -11℃
 *         @arg 6: -6℃ 
 *         @arg 7: -1℃ 
 * @param  otc: Temperature detector over-temperature control.
 *         This parameter can be one of the following values:
 *         @arg 0:89℃
 *         @arg 1:94℃
 *         @arg 2:98℃
 *         @arg 3:103℃
 *         @arg 4:108℃
 *         @arg 5:113℃
 *         @arg 6:118℃ 
 *         @arg 7:124℃
 * @retval  None
 */
void G_SENSOR_ANATsConfig(uint8_t utc, uint8_t otc)
{
    MSEC->SENSOR_THRES.bit.TS_UTC = utc;
    MSEC->SENSOR_THRES.bit.TS_OTC = otc;
}

/**
 * @method G_SENSOR_ShieldConfig
 * @brief  Config the shield.
 * @param  period: Shield working period.
 *         This parameter can be one of the following values:
 *         @arg PERIOD_32MS
 *         @arg PERIOD_125MS
 *         @arg PERIOD_500MS
 *         @arg PERIOD_999MS
 * @param  chknum: Shield check time.
 *         This parameter can be one of the following values:
 *         @arg SENSOR_SHIELD_CHK_WIN_Default
 *         @arg SENSOR_SHIELD_CHK_WIN_1
 *         @arg SENSOR_SHIELD_CHK_WIN_2
 *         @arg SENSOR_SHIELD_CHK_WIN_3
 *         @arg SENSOR_SHIELD_CHK_WIN_4
 * @retval  None
 */
void G_SENSOR_ShieldConfig(uint32_t period, uint32_t chknum)
{
    _ASSERT(IS_PERIOD_SHIELD(period));
    _ASSERT(IS_SENSOR_SHIELD_CHK_WIN(chknum));

    MSEC->SHIELD_CTRL.bit.PERIOD = period;
    MSEC->SHIELD_CTRL.bit.CHK_WIN = chknum;
}
/**
 * @method G_SENSOR_ShieldPortCmd
 * @brief  enable or disable Shield port.
 * @param  ShieldPort: Shield port.
 *         This parameter can be one of the following values:
 *         @arg SHIELD_Port_S0
 *         @arg SHIELD_Port_S1
 *         @arg SHIELD_Port_S2
 *         @arg SHIELD_Port_S3
 *         @arg SHIELD_Port_S4
 *         @arg SHIELD_Port_S5
 *         @arg SHIELD_Port_S6
 *         @arg SHIELD_Port_S7
 *         @arg SHIELD_Port_All
 * @param  NewState: new state of the sensor port
 *                   This parameter can be ENABLE or DISABLE
 * @retval  None
 */
void G_SENSOR_ShieldPortCmd(uint32_t ShieldPort, G_FunctionalState NewState)
{
    _ASSERT(IS_SHIELD_PORT(ShieldPort));

    uint32_t i = 0;
    volatile uint32_t tmpSensorShieldPortEn = 0;

    tmpSensorShieldPortEn = MSEC->SHIELD_EN.reg;

    for (i = 0; i < IN_SHIELD_NUM; i++)
    {
        if (0 != (ShieldPort & (0x1 << i)))
        {
            if (DISABLE != NewState)
            {
                SENSOR_T_S_PORT_CLEAR(tmpSensorShieldPortEn, i);
                SENSOR_T_S_PORT_ENABLE(tmpSensorShieldPortEn, i);
            }
            else
            {
                SENSOR_T_S_PORT_CLEAR(tmpSensorShieldPortEn, i);
                SENSOR_T_S_PORT_DISABLE(tmpSensorShieldPortEn, i);
            }
        }
    }

    MSEC->SHIELD_EN.reg = tmpSensorShieldPortEn;
}

/**
 * @method G_SENSOR_SecLockConfig
 * @brief  enable or disable sensor lock.
 * @param  SecLock: sensor lock.
 *         This parameter can be one of the following values:
 *         @arg SEC_LOCK_LOCK
 *         @arg ACTION_LOCK
 *         @arg TAMPER_LOCK
 *         @arg SENSOR_LOCK
 *         @arg SHIELD_LOCK
 * @param  NewState: new state of the sensor lock
 *                   This parameter can be ENABLE or DISABLE
 * @retval  None
 */
void G_SENSOR_SecLockConfig(uint32_t SecLock, G_FunctionalState NewState)
{
    _ASSERT(IS_SENSOR_LOCK(SecLock));
    _ASSERT(IS_FUNCTIONAL_STATE(NewState));

    if(NewState == ENABLE)
    {
        MSEC->LOCK.reg |= SecLock;
    }
    else
    {
        MSEC->LOCK.reg &= ~SecLock;
    }
}

/**
 * @method G_SENSOR_GetITStatus
 * @brief  get sensor's state.
 * @param  G_ITStatus: sensor state.
 *         Each bit means :
 *         @arg 0:7   tamps_alarm
 *         @arg 8:8   sensor_alarm
 *         @arg 16:16 shield_alarm
 *         @arg 17:17 soft_attack
 *         @arg 18:18 key_clear
 * @retval  TRUE or false
 */
G_Boolean G_SENSOR_GetITStatus(uint32_t G_ITStatus)
{
    _ASSERT(IS_SENSOR_IT(G_ITStatus));

    if ((MSEC->STATUS.reg & G_ITStatus) != 0)
    {
        return TRUE;
    }

    return FALSE;
}

/**
 * @method G_SENSOR_GetITStatusReg
 * @brief  Get sensor's state reg value.
 * @retval  sensor state.
 */
uint32_t G_SENSOR_GetITStatusReg(void)
{
    return MSEC->STATUS.reg;
}

/**
 * @method G_SENSOR_IRQCmd
 * @brief  Enable or disable sensor irq.
 * @param  sec_irq: sensor irq.
 *         This parameter can be one of the following values:
 *         @arg TAMPER_IRQ
 *         @arg SENSOR_IRQ
 *         @arg SHIELD_IRQ
 *         @arg SOFT_ATTACK_IRQ
 *         @arg KEY_CLEAR_IRQ
 *         @arg ALL_IRQ
 * @param  Statue: new state of the sensor check
 *                 This parameter can be ENABLE or DISABLE
 * @retval  none
 */
void G_SENSOR_IRQCmd(uint32_t sec_irq, G_FunctionalState Statue)
{
    _ASSERT(IS_SENSOR_IRQ(sec_irq));

    if (DISABLE != Statue)
    {
        MSEC->IE.reg |= sec_irq;
    }
    else
    {
        MSEC->IE.reg &= ~sec_irq;
    }
}

/**
 * @method G_SENSOR_ClearITPending
 * @brief  Clear sensor irq pending.
 * @retval  none
 */
void G_SENSOR_ClearITPending(void)
{
    MSEC->IRQ.reg = ALL_IRQ;
}

/**
 * @method G_SENSOR_ClearITPendingBit
 * @brief  Clear specified sensor interrupt.
 * @param  sec_irq: sensor irq.
 *         This parameter can be one of the following values:
 *         @arg TAMPER_IRQ
 *         @arg SENSOR_IRQ
 *         @arg SHIELD_IRQ
 *         @arg SOFT_ATTACK_IRQ
 *         @arg KEY_CLEAR_IRQ
 *         @arg ALL_IRQ
 * @retval  none
 */
void G_SENSOR_ClearITPendingBit(uint32_t sec_irq)
{
    _ASSERT(IS_SENSOR_IRQ(sec_irq));

    MSEC->IRQ.reg |= BIT(sec_irq);
}

/**
 * @method G_SENSOR_SetSecThreshold
 * @brief  Set sensor alert threshold.
 * @param  SecThre_val: sensor alert time.
 *         This parameter can be 0~0xf:
 * @retval  none
 */
void G_SENSOR_SetSecThreshold(uint32_t SecThre_val)
{
    _ASSERT(IS_SECTHRE_VAL(SecThre_val));

    MSEC->ALERT_FILT.bit.THOLD = SecThre_val;
}

/**
 * @method G_SENSOR_GetSecCnt
 * @brief  Get sensor alert cont.
 * @retval  sensor alert cont.
 */
uint32_t G_SENSOR_GetSecCnt(void)
{
    return MSEC->ALERT_FILT.bit.CNT;
}

/**
 * @method G_SENSOR_ClearSecCount
 * @brief  Clear sensor alert cont.
 * @retval  none
 */
void G_SENSOR_ClearSecCount(void)
{
    MSEC->ALERT_FILT.bit.CNT_CLR = 1;
}
#endif

/************************ (C) COPYRIGHT GKT *****END OF FILE****/
